package com.be.beadmin.project.impl;

import cn.hutool.core.util.ObjectUtil;
import com.be.beadmin.common.entity.PageEntity;
import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.common.utils.JpaQueryBuilder;
import com.be.beadmin.common.utils.JpaSortBuilder;
import com.be.beadmin.project.Util.MinioUtil;
import com.be.beadmin.project.dto.input.FileInfoDto;
import com.be.beadmin.project.dto.input.InfoAndPage;
import com.be.beadmin.project.dto.output.FileInfoEx;
import com.be.beadmin.project.entity.FileInfo;
import com.be.beadmin.project.entity.FileInfo_;
import com.be.beadmin.project.entity.Info;
import com.be.beadmin.project.mapper.ChangeMapper;
import com.be.beadmin.project.mapper.FileInfoMapper;
import com.be.beadmin.project.mapper.FileInfoMapperEx;
import com.be.beadmin.project.repository.ChangeRepository;
import com.be.beadmin.project.repository.FileInfoRepository;
import com.be.beadmin.project.repository.InfoRepository;
import com.be.beadmin.project.service.FileInfoService;
import com.be.beadmin.service.dto.output.DictDataEx;
import com.be.beadmin.service.entity.DictType;
import com.be.beadmin.service.impl.MinioService;
import com.be.beadmin.service.repository.DictTypeRepository;
import com.be.beadmin.service.service.DictDataService;
import com.be.beadmin.service.service.SerialNumberService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* @description 服务实现
* @author zmy
* @date 2023-02-15
**/
@Service
@RequiredArgsConstructor
public class FileInfoServiceImpl implements FileInfoService {

    @Autowired
    private  FileInfoRepository fileInfoRepository;
    @Autowired
    private  FileInfoMapper fileInfoMapper;
    @Autowired
    private  FileInfoMapperEx fileInfoExMapper;

    @Autowired
    private FileInfoService fileInfoService;

    @Autowired
    private InfoRepository infoRepository;

    @Autowired
    private ChangeMapper changeMapper;
    @Autowired
    private ChangeRepository changeRepository;


    @Autowired
    private DictTypeRepository dictTypeRepository;
    @Autowired
    private DictDataService dictDataService;

    @Autowired
    private SerialNumberService serialNumberService;

    @Autowired
    private MinioService minioService;
    MinioUtil minioUtil = new MinioUtil();

    @Override
    public Page<FileInfoEx> getFileInfoByPage(PageEntity pageEntity) {
            Pageable pageable = PageRequest.of(
            pageEntity.getCurrent() -1,
            pageEntity.getPageSize());
            Page<FileInfo> page = fileInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilder.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(FileInfo_.delete), 0); //过滤为0
                    list.add(pre2);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(FileInfo_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                    }
                    , pageable);
            Page<FileInfoEx> page1 = page.map(fileInfoExMapper::toEntity);
            return page1;

    }

    @Override
    public void addFileInfo(FileInfoDto fileInfoDto) {
            FileInfo result = fileInfoRepository.findFileInfoByIdAndDelete(fileInfoDto.getId(), 0);
            if(ObjectUtil.isNotEmpty(result)) {
                throw new BeadminException("FileInfo不存在,请重新查询");
            }
            FileInfo fileInfo1 = fileInfoMapper.toEntity(fileInfoDto);
            fileInfo1.setFileCode(serialNumberService.getNextSnByCode("FileCode"));
            fileInfoRepository.save(fileInfo1);
    }

    @Override
    public void updateFileInfo(FileInfoDto fileInfoDto) {
            FileInfo fileInfo = fileInfoRepository.findFileInfoById(fileInfoDto.getId());
            fileInfo = fileInfoMapper.toEntity(fileInfoDto);
            fileInfoRepository.save(fileInfo);
    }


    @Override
    public void delFileInfo(String id) {
        FileInfo fileInfo = fileInfoRepository.findFileInfoById(id);
        fileInfo.setDelete(1);
        fileInfoRepository.save(fileInfo);
    }

    @Override
    public void delFileInfos (List<String> ids) { }

    @Override
    public List<String> getFileType() {
        DictType dictType = dictTypeRepository.findDictTypeByDictName("项目附件上传类型");

        List<DictDataEx> fileType =  dictDataService.getDictDataExByDictTypeId(dictType);
        List<String> fileTypeList = new ArrayList<>();
        fileType.forEach(role-> fileTypeList.add(role.getKeyName()));


        return fileTypeList;

    }



    @Override
    public void updateFileInfo2(String id,String infoId, String category, MultipartFile multipartFile, String memo,String bucketName) throws Exception {

        //对文件进行操作
        FileInfo fileInfo = fileInfoRepository.findFileInfoById(id);
        FileInfoDto fileInfoDto = fileInfoMapper.toDto(fileInfo);
        //System.out.println(fileInfoDto);
        if(multipartFile!=null) {
            //文件名,前进加项目名称
            String fileName = multipartFile.getOriginalFilename();
            fileInfoDto.setFileName(fileInfoDto.getProjectName()+"-"+fileName);
            //文件大小
            BigDecimal fileSize = new BigDecimal(multipartFile.getSize());
            fileInfoDto.setFileSize(fileSize);
            //文件类型
            fileInfoDto.setCategory(category);
            //流水号
            //fileInfoDto.setSerialNo(serialNo);
            //文件后缀
            //System.out.println(fileName.substring(fileName.lastIndexOf(".")+1));
            fileInfoDto.setFileExtEndDate(fileName.substring(fileName.lastIndexOf(".")+1));
            //设置bucketName
            fileInfoDto.setBucketName(bucketName);
            //处理文件
            //minioUtil.uploadFile(multipartFile,fileInfoDto.getProjectName()+"-"+fileName,bucketName);
            minioService.uploadFile(bucketName,fileInfoDto.getProjectName()+"-"+fileName,multipartFile);
        }
        fileInfoDto.setCategory(category);
        if(memo!=null) {
            fileInfoDto.setMemo(memo);
        }
        fileInfoService.updateFileInfo(fileInfoDto);

    }

    @Override
    public void uploadFileInfo(String infoId, String category, MultipartFile[] multipartFile,String fileName,String memo,String bucketName) throws Exception {
        //将info表项目状态改成已发布

        Info info = infoRepository.findInfoById(infoId);
//        InfoDto infoDto = infoMapper.toDto(info);
//        infoService.updateInfo(infoDto);

        //对文件进行操作

        for(MultipartFile file:multipartFile) {
            FileInfo fileInfoDto = new FileInfo();
            //文件名
//        if (fileName==null||fileName.equals("")) {
//
//            fileName = multipartFile.getOriginalFilename();
//        }
            fileName = file.getOriginalFilename();



            //文件后缀
            String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
            fileInfoDto.setFileExtEndDate(ext);

            //判断同一个项目是否有相同的文件名
            int f = fileInfoRepository.countFileInfosByFileNameAndProjectNameAndDelete(fileName, info.getProjectName(), 0);

            String version;
            while (true) {
                version = "v1." + f;
                int num = fileInfoRepository.countFileInfosByFileNameAndVersionAndDelete(fileName, version, 0);
                if (num == 0) {
                    break;
                } else {
                    f++;
                }
            }
            //System.out.println("version:"+version);
            fileInfoDto.setVersion(version);
            fileInfoDto.setFileName(fileName);

            //文件大小
            BigDecimal fileSize = new BigDecimal(file.getSize());
            fileInfoDto.setFileSize(fileSize);
            //文件类型
            fileInfoDto.setCategory(category);
            //流水号
            //fileInfoDto.setSerialNo(serialNo);
            String fileCode = serialNumberService.getNextSnByCode("FileCode");
            fileInfoDto.setFileCode(fileCode);
            //项目id
            fileInfoDto.setInfoId(infoId);
            //项目名称
            fileInfoDto.setProjectName(info.getProjectName());
            //备注
            fileInfoDto.setMemo(memo);
            //设置bucketName
            fileInfoDto.setBucketName(bucketName);
            //System.out.println(fileInfoDto.toString());
            //处理文件

            String newFileName = fileName.substring(0, fileName.lastIndexOf(".")) + "-" + version + "." + ext;
            //minioUtil.uploadFile(multipartFile,newFileName,bucketName);
            minioService.uploadFile(bucketName, newFileName, file);
            fileInfoRepository.save(fileInfoDto);
        }

//        FileInfo fileInfoByFileName = fileInfoRepository.findFileInfoByFileName(info.getProjectName() + "-" + fileName);
//        if (fileInfoByFileName == null||fileInfoByFileName.equals("")) {
//            fileInfoService.addFileInfo(fileInfoDto);
//        }
//        else{
//            fileInfoService.updateFileInfo(fileInfoDto);
//        }
    }


    public InputStream download(String bucketName, String id, HttpServletResponse response){
        FileInfo fileInfo = fileInfoRepository.findFileInfoByIdAndDelete(id, 0);
        String fileName = fileInfo.getFileName();
        String newFileName = fileName.substring(0,fileName.lastIndexOf(".")) +"-"+ fileInfo.getVersion()+"."+fileInfo.getFileExtEndDate();
        InputStream inputStream = minioService.downloadOne(bucketName, newFileName);
        return inputStream;
        // minioUtil.downloadFile(bucketName,fileInfo.getFileName(),response);

    }

    /**
     * 指定项目ID获取附件分页信息
     *
     * @param infoAndPage
     * @return
     */
    @Override
    public Page<FileInfoEx> getFileInfoByPageAndInfoId(InfoAndPage infoAndPage) {
        PageEntity pageEntity = infoAndPage.getPageEntity();
        String infoId = infoAndPage.getInfoId();
        if (infoId == null) throw new BeadminException("需要指定项目Id");
        Pageable pageable = PageRequest.of(
                pageEntity.getCurrent() -1,
                pageEntity.getPageSize());
        Page<FileInfo> page = fileInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilder.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(FileInfo_.delete), 0); //过滤为0
                    list.add(pre2);
                    Predicate pre3 = criteriaBuilder.equal(root.get(FileInfo_.infoId), infoId); //过滤为0
                    list.add(pre3);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(FileInfo_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                }
                , pageable);
        Page<FileInfoEx> page1 = page.map(fileInfoExMapper::toEntity);
        return page1;
    }
}